import java.util.concurrent.locks.Lock;

public class MovePolice implements Runnable{

		Police pol;
		ComponentPanel[][] componentpanel;
		int componentPanelSize;
		Empty empty = new Empty();
		Lock lock;
		int episode = 1;
		public MovePolice(Police pol,ComponentPanel[][] c, int cSize,Lock lock){
			this.lock = lock;
		    this.componentpanel=c;
		    this.componentPanelSize=cSize;
			this.pol = pol;
			
		}


		public void run() {
			try {
				
				while(true){

					Thread.sleep(Police.volume);
					pol.oldState = pol.currentState;
					
					if(pol.nextState==null){
						pol.currentState = findNextState(pol.oldState);
					}
					else
						pol.currentState = pol.nextState;
					lock.lock();
					
					if(pol.oldState!=pol.currentState){
						componentpanel[pol.oldState.x][pol.oldState.y].component=new Empty();
						componentpanel[pol.oldState.x][pol.oldState.y].putComponent(componentpanel[pol.oldState.x][pol.oldState.y].component.getImage());
					
					}
					pol.nextState = findNextState(pol.currentState);
					pol.counter++;
					
					if(componentpanel[pol.currentState.x][pol.currentState.y].component instanceof Racer){
						startNewEpisode();
					}
					else 
						pol.temporal.Learn(pol);
					
					componentpanel[pol.currentState.x][pol.currentState.y].component=pol;
					componentpanel[pol.currentState.x][pol.currentState.y].putComponent(componentpanel[pol.currentState.x][pol.currentState.y].component.getImage());
					lock.unlock();
					}
			}
				
			 catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
		public void startNewEpisode(){
			pol.temporal.reward = 10;
			pol.total+=pol.counter;
			pol.temporal.Learn(pol);
			pol.temporal.reward = 0;
			System.out.println("pol :  "+ pol.which + "  episode num: "+ episode +"  trial:"  + pol.counter +"   average:"+(pol.total)/episode);
			pol.counter = 0;  
			pol.currentState.x = pol.initialState.x;
			pol.currentState.y = pol.initialState.y;
			pol.nextState = null;
			episode++;
			
		}
		public  int findMaxDoor(State st){
			int k = 0;
			double value = -1000000;
			for (int i=0;i<4;i++){
				if(pol.qValues[st.x][st.y][i] > value){
					value=pol.qValues[st.x][st.y][i];
					k=i;
				}
			}
			return k;
		}
		private synchronized State findNextState(State st) {
			State s = detectRacer(st);
			State state = null;
			if(s!=null){
				state = catchRacer(st,s);
			}
			if(state==null){
				if(pol.qValues[st.x][st.y][0] == (pol.qValues[st.x][st.y][1]) &&
						   pol.qValues[st.x][st.y][0] == (pol.qValues[st.x][st.y][2]) &&
						   pol.qValues[st.x][st.y][0] == (pol.qValues[st.x][st.y][3])){
							   state = findRandomWay(st);
				}
				else{
					
					double randomDouble = Math.random();
					
					if(randomDouble > pol.temporal.epsilon){
						int tempK = -1 ;double temp = 0;
						System.out.println(pol.temporal.epsilon);
						while(true){
							
							int k  = findMaxDoor(st);
							if(k==0){
								if(st.x>0){
									
									if((componentpanel[st.x-1][st.y].component instanceof Racer) || (componentpanel[st.x-1][st.y].component instanceof Empty)){		
										if(tempK!=-1)
											pol.qValues[st.x][st.y][tempK] = temp;
										state = setState(st,-1,0,0);
										break;
									}
									else{
										tempK = k;
										temp = pol.qValues[st.x][st.y][k];
										pol.qValues[st.x][st.y][k] = -3000000;
									}
								}
								else
									pol.qValues[st.x][st.y][k]=-5000000;
								
							}
						
							else if(k==1){
								if(st.y>0){
									if((componentpanel[st.x][st.y-1].component instanceof Racer) || (componentpanel[st.x][st.y-1].component instanceof Empty)){
										if(tempK!=-1)
											pol.qValues[st.x][st.y][tempK] = temp;
										tempK = -1;
										state=setState(st,0,-1,1);
										break;
									}
									else{
										tempK = k;
										temp = pol.qValues[st.x][st.y][k];
										pol.qValues[st.x][st.y][k] = -3000000;
									}
								}
								else{
									pol.qValues[st.x][st.y][k]=-5000000;
								}
							}

							else if(k==2){
								if(st.x<componentPanelSize-1){
									if((componentpanel[st.x+1][st.y].component instanceof Racer) || (componentpanel[st.x+1][st.y].component instanceof Empty)){
										if(tempK!=-1)
											pol.qValues[st.x][st.y][tempK] = temp;
										tempK = -1;
										state=setState(st,1,0,2);
										break;
									}
									else{
										tempK = k;
										temp = pol.qValues[st.x][st.y][k];
										pol.qValues[st.x][st.y][k] = -3000000;
									}
								}
								else{
									pol.qValues[st.x][st.y][k]=-5000000;
								}
							}
						
							else if(k==3){
								if(st.y<componentPanelSize-1){
									if((componentpanel[st.x][st.y+1].component instanceof Racer) || (componentpanel[st.x][st.y+1].component instanceof Empty)){
										if(tempK!=-1)
											pol.qValues[st.x][st.y][tempK] = temp;
										tempK = -1;
										state=setState(st,0,1,3);
										break;
									}
									else{
										tempK = k;
										temp = pol.qValues[st.x][st.y][k];
										pol.qValues[st.x][st.y][k] = -3000000;
									}
								}
								else
									pol.qValues[st.x][st.y][k]=-5000000;
							}	
						
						}
					}
					
					else{
						state = findRandomWay(st);
					}
				}
			}
				
			return state;
		}


		public State catchRacer(State polst,State racst){
			State s = null;
			if(racst!=null){
				if(racst.x>polst.x){
					if(componentpanel[polst.x+1][polst.y].component instanceof Empty || componentpanel[polst.x+1][polst.y].component instanceof Racer){
						return s = setState(polst,1,0,2);
					}
				}
				if(racst.y > polst.y){
					if(componentpanel[polst.x][polst.y+1].component instanceof Empty || componentpanel[polst.x][polst.y+1].component instanceof Racer){
						return s = setState(polst,0,1,3);
					}
				}
				if(racst.x<polst.x){
					if(componentpanel[polst.x-1][polst.y].component instanceof Empty || componentpanel[polst.x-1][polst.y].component instanceof Racer){
						return s = setState(polst,-1,0,0);
					}
				}
				if(racst.y < polst.y){
					if(componentpanel[polst.x][polst.y-1].component instanceof Empty || componentpanel[polst.x][polst.y-1].component instanceof Racer){
						return s = setState(polst,0,-1,1);
					}
				}
			}
			return s;
		}
		public State setState(State st,int x, int y,int action){
			
			State state = new State(st.x + x,st.y + y);
			
			st.action=action;
			return state;
		}
		public State  detectRacer(State s){
			int firstx,firsty,secondx,secondy;
			
			firstx = secondx = s.x;
			firsty = secondy = s.y;
			int step = 2;
			
			while(firstx>0 && step>0){
				firstx--;
				step--;
			}
			step = 2;
          
			while(firsty>0 && step>0){
				firsty--;
				step--;
			}
			step = 2;
           
           while(secondx<componentPanelSize-1 && step>0){
        	   secondx++;
        	   step--;
           }
           step = 2;
           
           while(secondy<componentPanelSize-1 && step>0){
        	   secondy++;
        	   step--;
           }
           
           for(int i=firstx; i<=secondx; i++)
        	   for(int j=firsty; j<=secondy; j++){
        		   if(componentpanel[i][j].component instanceof Racer && !componentpanel[i][j].isHidden)
        			   return new State(i,j) ;
        		   
        	   }
           
           return null;
		
		}
		
		public State findRandomWay(State st){
			State state;
			while(true){
				
				int random = (int) (Math.random()*4);	
				//System.out.println(random +" (" + racer.currentState.x +""+racer.currentState.y+")");
				if(random == 0 && st.x>0 &&(componentpanel[st.x-1][st.y].component instanceof Empty || componentpanel[st.x-1][st.y].component instanceof Racer)){
					state = setState(st,-1,0,0);
					break;
				}
				else if(random == 1 && st.y>0 && (componentpanel[st.x][st.y-1].component instanceof Empty || componentpanel[st.x][st.y-1].component instanceof Racer)){
					state=setState(st,0,-1,1);
					break;
				}
				else if(random == 2 && st.x<componentPanelSize-1 && (componentpanel[st.x+1][st.y].component instanceof Empty || componentpanel[st.x+1][st.y].component instanceof Racer)){
					state=setState(st,1,0,2);
					break;
				}	
				else if(random == 3 && st.y<componentPanelSize-1 && (componentpanel[st.x][st.y+1].component instanceof Empty || componentpanel[st.x][st.y+1].component instanceof Racer)){
					state=setState(st,0,1,3);
					break;
				}
			}
			return state;
		}
	}
	